package com.bookmall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bookmall.common.constant.ExceptionTypeConstants;
import com.bookmall.common.constant.PageSizeConstants;
import com.bookmall.common.constant.MyInfoTypeConstants;
import com.bookmall.common.constant.MyStatusConstants;
import com.bookmall.common.entity.es.EsModel;
import com.bookmall.common.entity.to.MemberInfoTo;
import com.bookmall.common.utils.MyQuery;
import com.bookmall.common.utils.PageUtils;
import com.bookmall.product.domain.*;
import com.bookmall.product.domain.vo.*;
import com.bookmall.product.feign.MemberInfoFeignService;
import com.bookmall.product.feign.SearchFeignService;
import com.bookmall.product.interceptor.ProductInterceptor;
import com.bookmall.product.mapper.*;
import com.bookmall.product.service.IBookCategoryService;
import com.bookmall.product.service.IBookInfoImagesService;
import com.bookmall.product.service.IBookInfoService;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.utils.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author 胡菜鸡
 * @Create 2022-02-18-15:31
 */
@Service("bookInfoService")
public class BookInfoServiceImpl extends ServiceImpl<BookInfoMapper, BookInfo> implements IBookInfoService {
    @Autowired
    private BookInfoMapper bookInfoMapper;

    @Autowired
    private BookCategoryMapper categoryMapper;

    @Autowired
    private IBookCategoryService categoryService;

    @Autowired
    private IBookInfoImagesService bookImagesService;

    @Autowired
    private BookInfoImagesMapper bookImagesMapper;

    @Autowired
    private BookInfoDescMapper bookInfoDescMapper;

    @Autowired
    private MemberInfoFeignService memberInfoFeignService;

    @Autowired
    private SearchFeignService searchFeignService;

    /**
     * 根据对象内非空的属性进行分页查询列表
     * @author 胡菜鸡
     * @date 2022/2/19 16:48
     */
    @Override
    public PageUtils selectBookInfoList(BookInfoVo bookInfoVo) {
        LambdaQueryWrapper<BookInfo> wrapper = new LambdaQueryWrapper<>();

        //重新拼接分类查询条件（查询此分类和其子分类下的所有书籍）
        if(bookInfoVo.getBookType() != null){
            //查询此分类所有的子分类
            List<BookCategory> childrenCategory = categoryService.getChildrenCategory(bookInfoVo.getBookType());
            //存在子分类，则重新设定书籍分类的查询条件，否则正常查询
            if(childrenCategory != null && childrenCategory.size() > 0) {
                List<String> categoryIds = childrenCategory.stream().map(categoryEntity -> {
                    return categoryEntity.getId();
                }).collect(Collectors.toList());
                //将此分类本身也添加进去
                categoryIds.add(bookInfoVo.getBookType());
                //通过 bookType in ids 查询
                wrapper.in(BookInfo::getBookType, categoryIds);
                //删除原来的分类查询条件
                bookInfoVo.setBookType(null);
            }
        }

        //价格区间查询条件
        if(bookInfoVo.getMaxPrice() != null){
            wrapper.lt(BookInfo::getBookPrice, bookInfoVo.getMaxPrice());
        }
        if(bookInfoVo.getMinPrice() != null){
            wrapper.gt(BookInfo::getBookPrice, bookInfoVo.getMinPrice());
        }

        //其他查询条件
        wrapper.setEntity(bookInfoVo);

        //开始查询
        IPage<BookInfo> page = this.page(new MyQuery<BookInfo>().getPage(bookInfoVo), wrapper);
        return new PageUtils(page);
    }

    /**
     * 根据id查询书籍信息（异步查询）
     * @author 胡菜鸡
     * @date 2022/2/20 18:19
     */
    @Override
    public BookInfoVo selectBookInfoById(String id) {
        BookInfoVo bookInfoVo = new BookInfoVo();
        // 查找书籍基本信息
        BookInfo bookInfo = bookInfoMapper.selectById(id);
        BeanUtils.copyProperties(bookInfo, bookInfoVo);
        // 查找书籍图片集
        String imagesUrl = bookImagesService.selectImageUrl(id);
        bookInfoVo.setImageUrl(imagesUrl);
        // 查找书籍详细描述
        BookInfoDesc bookInfoDesc = bookInfoDescMapper.selectById(id);
        if (bookInfoDesc != null) {
            bookInfoVo.setBookDesc(bookInfoDesc.getBookDesc());
        }
        return bookInfoVo;
    }

    /**
     * 修改书籍上架信息
     * @author 胡菜鸡
     * @date 2022/2/20 17:11
     */
    @Override
    public int updateBookStatus(BookInfo bookInfo) {
        bookInfo.setUpdateBy(SecurityUtils.getUsername());
        bookInfo.setUpdateTime(DateUtils.getNowDate());
        return bookInfoMapper.updateById(bookInfo);
    }

    /**
     * 书籍上架
     * @author 胡菜鸡
     * @date 2022/4/8 14:32
     */
    @Override
    public int up(String id, int status) {
        //组装需要的数据
        EsModel esModel = new EsModel();

        //1、查出书籍的基本信息
        BookInfo bookInfo = bookInfoMapper.selectById(id);
        if(bookInfo == null) {
            throw new ServiceException("上架书籍不存在");
        }
        BeanUtils.copyProperties(bookInfo, esModel);
        esModel.setHasStock(bookInfo.getBookCount() > 0);
        esModel.setStatus(status);

        //2、远程查询上架此书籍的用户信息
        AjaxResult userInfo = memberInfoFeignService.getInfoByStuId(bookInfo.getUid());
        if(userInfo.get("data") != null){
            MemberInfoTo memberInfoTo = userInfo.getData("data", new TypeReference<MemberInfoTo>(){});
            esModel.setNickname(memberInfoTo.getNickname());
            esModel.setProvince(memberInfoTo.getProvince());
            esModel.setUniversity(memberInfoTo.getUniversity());
            esModel.setUid(memberInfoTo.getStuId());
        }
        //3、查出此书籍的图片信息
        LambdaQueryWrapper<BookInfoImages> imageWrapper = new LambdaQueryWrapper<>();
        List<BookInfoImages> bookInfoImages = bookImagesMapper.selectList(imageWrapper
                .eq(BookInfoImages::getBookId, id)
                .eq(BookInfoImages::getImageType, MyInfoTypeConstants.BOOK_IMAGE));
        List<EsModel.BookImage> bookImageList = bookInfoImages.stream().map(bookInfoImage -> {
            EsModel.BookImage bookImage = new EsModel.BookImage();
            BeanUtils.copyProperties(bookInfoImage, bookImage);
            return bookImage;
        }).collect(Collectors.toList());
        esModel.setBookImages(bookImageList);

        //4、查出此书籍的详细信息
        BookInfoDesc bookInfoDesc = bookInfoDescMapper.selectById(id);
        if(bookInfoDesc != null){
            esModel.setBookDesc(bookInfoDesc.getBookDesc());
        }

        //5、数据发送给es进行保存
        List<EsModel> data = new ArrayList<>();
        data.add(esModel);
        AjaxResult ajaxResult = searchFeignService.bookStatusUp(data);

        String string = ajaxResult.get(AjaxResult.CODE_TAG).toString();
        if(string.equals("200")){
            // 远程调用成功

            //修改书籍上架状态
            BookInfo bookInfoStatus = new BookInfo();
            bookInfoStatus.setId(id);
            bookInfoStatus.setStatus(status);
            updateBookStatus(bookInfoStatus);
            return 1;
        } else {
            // 远程调用失败
            //TODO 上架失败后的一些高级设置（重复调用的问题？接口幂等性？重试机制？）
            return 0;
        }
    }

    /**
     * 书籍下架
     * @author 胡菜鸡
     * @date 2022/4/29 17:43
     */
    @Override
    public int down(String id, int status) {
        BookInfo bookInfo = new BookInfo();
        bookInfo.setId(id);
        bookInfo.setStatus(MyStatusConstants.BOOK_DOWN);
        if(!updateById(bookInfo)){
            throw new ServiceException("书籍下架失败");
        }
        return up(id, status);
    }

    /**
     * 保存商品到喜欢
     * @author 胡菜鸡
     * @date 2022/5/3 19:03
     */
    @Override
    public Boolean addToLikes(String bookId) {
        MemberInfoTo memberInfoTo = ProductInterceptor.threadLocal.get();
        BookInfo bookInfo = this.getById(bookId);

        MemberLikeBooksVo memberLikeBooks = new MemberLikeBooksVo();
        memberLikeBooks.setMemberId(memberInfoTo.getId());
        memberLikeBooks.setBookId(bookId);
        memberLikeBooks.setBookName(bookInfo.getBookName());
        memberLikeBooks.setPublishMemberId(bookInfo.getUid());
        memberLikeBooks.setDisplay(0);

        AjaxResult ajaxResult = memberInfoFeignService.addBookLikes(memberLikeBooks);
        if(ajaxResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.SUCCESS)){
            return true;
        } else {
            return false;
        }
    }

    /**
     * 新增书籍
     * @author 胡菜鸡
     * @date 2022/2/20 17:51
     */
    @Override
    @Transactional
    public boolean insertBookInfo(BookInfoVo bookInfoVo) {
        AjaxResult ajaxResult = memberInfoFeignService.getInfoByStuId(bookInfoVo.getUid());
        if(ajaxResult.get(AjaxResult.CODE_TAG).equals(HttpStatus.ERROR)){
            throw new ServiceException("学生学号不存在");
        }
        /*
            插入书籍信息
         */
        BookInfo bookInfo = new BookInfo();
        BeanUtils.copyProperties(bookInfoVo, bookInfo);
        String imagesUrl = bookInfoVo.getImageUrl();
        bookInfo.setCreateBy(SecurityUtils.getUsername());
        bookInfo.setCreateTime(DateUtils.getNowDate());
        //设置优惠比率
        BigDecimal percent = bookInfo.getBookOriginalPrice()
                .subtract(bookInfo.getBookPrice())
                .divide(bookInfo.getBookOriginalPrice(), 2, BigDecimal.ROUND_CEILING)
                .multiply(new BigDecimal(100));
        bookInfo.setPercent(percent);
        //设置书籍类别名称
        BookInfo bookInfoResult = this.setBookTypeName(bookInfo);
        int i = bookInfoMapper.insert(bookInfoResult);

        /*
            插入书籍图片信息
         */
        int j = 1, m = 1;
        if(!StringUtils.isBlank(imagesUrl)){
            j = bookImagesService.insertImagesWithUrl(imagesUrl, bookInfoResult.getId(), MyInfoTypeConstants.BOOK_IMAGE);
        }

        /*
            插入书籍详细描述信息
         */
        BookInfoDesc bookInfoDesc = new BookInfoDesc();
        bookInfoDesc.setId(bookInfoResult.getId());
        bookInfoDesc.setBookDesc(bookInfoVo.getBookDesc());
        int k = bookInfoDescMapper.insert(bookInfoDesc);

        return i > 0 & j > 0 & k > 0 & m > 0;
    }

    /**
     * 修改书籍信息
     * @author 胡菜鸡
     * @date 2022/2/20 18:53
     */
    @Override
    @Transactional
    public boolean updateBookInfo(BookInfoVo bookInfoVo) {
        /*
            修改书籍信息
         */
        BookInfo bookInfo = new BookInfo();
        BeanUtils.copyProperties(bookInfoVo, bookInfo);
        bookInfo.setUpdateBy(SecurityUtils.getUsername());
        bookInfo.setUpdateTime(DateUtils.getNowDate());
        //设置优惠比率
        BigDecimal percent = bookInfo.getBookOriginalPrice()
                .subtract(bookInfo.getBookPrice())
                .divide(bookInfo.getBookOriginalPrice(), 2, BigDecimal.ROUND_CEILING)
                .multiply(new BigDecimal(100));
        bookInfo.setPercent(percent);
        //设置书籍类别名称
        BookInfo bookInfoResult = setBookTypeName(bookInfo);
        int i = bookInfoMapper.updateById(bookInfoResult);

        /*
            修改书籍图片
         */
        int j = 1, m = 1;
        String imagesUrl = bookInfoVo.getImageUrl();
        if(!StringUtils.isBlank(imagesUrl)) {
            //删除原来的图片
            LambdaQueryWrapper<BookInfoImages> wrapper = new LambdaQueryWrapper<>();
            bookImagesMapper.delete(wrapper.eq(BookInfoImages::getBookId, bookInfo.getId()));

            //插入新的图片
            j = bookImagesService.insertImagesWithUrl(imagesUrl, bookInfoResult.getId(), MyInfoTypeConstants.BOOK_IMAGE);
        }

        /*
            修改书籍书籍详细描述
         */
        BookInfoDesc bookInfoDesc = new BookInfoDesc();
        bookInfoDesc.setId(bookInfoVo.getId());
        bookInfoDesc.setBookDesc(bookInfoVo.getBookDesc());
        int k = bookInfoDescMapper.updateById(bookInfoDesc);
        return i > 0 & j > 0 & k > 0;
    }

    /**
     * 设置书籍分类名称
     * @author 胡菜鸡
     * @date 2022/3/12 16:26
     */
    private BookInfo setBookTypeName(BookInfo bookInfo){
        //书籍类型是否为空
        if(!StringUtils.isBlank(bookInfo.getBookType())){
            //查询此书籍类型
            BookCategory bookCategory = categoryMapper.selectById(bookInfo.getBookType());
            if(bookCategory != null) {
                // 书籍类型存在
                bookInfo.setBookTypeName(bookCategory.getCatName());
                return bookInfo;
            }
        }
        // 不存在
        bookInfo.setBookType(null);
        bookInfo.setBookTypeName("无");
        return bookInfo;
    }

    /**
     * 批量删除书籍
     * @author 胡菜鸡
     * @date 2022/3/12 21:30
     */
    @Override
    @Transactional
    public int deleteBookInfoByIds(List<String> ids) {
        LambdaQueryWrapper<BookInfoImages> wrapper = new LambdaQueryWrapper<>();
        bookImagesMapper.delete(wrapper.in(BookInfoImages::getBookId, ids));
        bookInfoDescMapper.deleteBatchIds(ids);
        return bookInfoMapper.deleteBatchIds(ids);
    }

    /**
     * 查询最新上架的书籍
     * @author 胡菜鸡
     * @date 2022/3/21 21:05
     */
    @Override
    public List<BookInfoVo> selectLatestBookInfoList() {
        BookInfo bookInfo = new BookInfo();
        bookInfo.setPageStart(0);
        bookInfo.setPageSize(PageSizeConstants.MINI*10);
        List<BookInfo> bookInfoList = bookInfoMapper.selectBookInfoListWithImagesAndDesc(bookInfo);
        if(bookInfoList.size() > PageSizeConstants.MINI){
            bookInfoList = bookInfoList.subList(0, PageSizeConstants.SMALL);
        }

        return setDataFormat(bookInfoList);
    }

    /**
     * 查询打折力度最高的书籍集合
     * @author 胡菜鸡
     * @date 2022/3/31 13:52
     */
    @Override
    public List<BookInfoVo> selectSpecialPriceBookList() {
        BookInfo bookInfo = new BookInfo();
        bookInfo.setPageStart(0);
        bookInfo.setPageSize(PageSizeConstants.MEDIUM*10);
        List<BookInfo> bookInfoList = bookInfoMapper.selectBookInfoListWithImages(bookInfo);
        if(bookInfoList.size() > PageSizeConstants.MEDIUM){
            bookInfoList = bookInfoList.subList(0, PageSizeConstants.MEDIUM);
        }
        return setDataFormat(bookInfoList);
    }

    /**
     * 查询最便宜的书籍
     * @author 胡菜鸡
     * @date 2022/4/20 14:35
     */
    @Override
    public List<BookInfoVo> selectMinPriceBook() {
        LambdaQueryWrapper<BookInfo> wrapper = new LambdaQueryWrapper<>();
        Page<BookInfo> page = bookInfoMapper.selectPage(new Page<>(1, PageSizeConstants.BIG),
                wrapper.eq(BookInfo::getStatus, MyStatusConstants.BOOK_UP).orderByAsc(BookInfo::getBookPrice));
        List<BookInfo> collect = getImageAndDescInfo(page.getRecords());
        return setDataFormat(collect);
    }

    /**
     * 查出新旧程度最高的书籍
     * @author 胡菜鸡
     * @date 2022/4/20 16:05
     */
    @Override
    public List<BookInfoVo> selectMaxLevelBook() {
        LambdaQueryWrapper<BookInfo> wrapper = new LambdaQueryWrapper<>();
        Page<BookInfo> page = bookInfoMapper.selectPage(new Page<>(1, PageSizeConstants.HUGE),
                wrapper.eq(BookInfo::getStatus, MyStatusConstants.BOOK_UP).orderByDesc(BookInfo::getBookLevel));
        List<BookInfo> collect = getImageAndDescInfo(page.getRecords());
        return setDataFormat(collect);
    }

    /**
     * 为某个订单锁定库存
     * @author 胡菜鸡
     * @date 2022/4/25 9:15
     */
    @Override
    @Transactional
    public Boolean orderLockStock(WareBookLockVo wareBookLockVo) {
        for (WareBookLockVo.OrderItemsLock item : wareBookLockVo.getLocks()) {
            //锁库存
            Long result = bookInfoMapper.lockBookStock(item.getId(), item.getCount());
            if(result == 0){
                throw new ServiceException("商品库存不足", ExceptionTypeConstants.PRODUCT_WARE_NO_STOCK);
            }
        }

        //全部商品库存锁定成功
        return true;
    }

    /**
     * 根据id批量修改书籍基本信息
     * @author 胡菜鸡
     * @date 2022/4/26 14:56
     */
    @Override
    @Transactional
    public int updateBookLockCountBatchById(List<BookWareInfoVo> bookWareInfoVo) {
        List<BookInfo> collect = bookWareInfoVo.stream().map(bookWare -> {
            BookInfo bookInfo = this.getById(bookWare.getId());
            bookInfo.setCountStockLocked(bookInfo.getCountStockLocked() - bookWare.getCountStockLocked());
            return bookInfo;
        }).collect(Collectors.toList());
        return this.updateBatchById(collect) ? 1 : 0;
    }

    /**
     * 根据书籍id查询书籍图片和书籍描述
     * @author 胡菜鸡
     * @date 2022/4/20 16:08
     */
    private List<BookInfo> getImageAndDescInfo(List<BookInfo> bookInfoList){
        List<BookInfo> collect = bookInfoList.stream().map(bookInfo -> {
            LambdaQueryWrapper<BookInfoImages> imageWrapper = new LambdaQueryWrapper<>();
            List<BookInfoImages> bookInfoImages = bookImagesMapper.selectList(imageWrapper.eq(BookInfoImages::getBookId, bookInfo.getId()));
            bookInfo.setBookInfoImages(bookInfoImages);
            BookInfoDesc bookInfoDesc = bookInfoDescMapper.selectById(bookInfo.getId());
            bookInfo.setBookDesc(bookInfoDesc.getBookDesc());
            return bookInfo;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 调整数据格式
     * @author 胡菜鸡
     * @date 2022/3/31 16:02
     */
    private List<BookInfoVo> setDataFormat(List<BookInfo> bookInfoList){
        List<BookInfoVo> collect = bookInfoList.stream().map(bookInfoEntity -> {
            BookInfoVo bookInfoVo = new BookInfoVo();
            BeanUtils.copyProperties(bookInfoEntity, bookInfoVo);

            //设置书籍默认图片地址
            List<String> defaultImagesUrl = bookInfoVo.getBookInfoImages().stream()
                    .filter(bookInfoImages -> bookInfoImages.getDefaultImage().equals(0))
                    .map(bookInfoImages -> bookInfoImages.getImageUrl())
                    .collect(Collectors.toList());
            bookInfoVo.setDefaultImagesUrl(defaultImagesUrl);

            //修改日期格式为中文
            SimpleDateFormat simple = new SimpleDateFormat("yyyy年MM月dd日");
            bookInfoVo.setSellTime(simple.format(bookInfoEntity.getCreateTime()));

            return bookInfoVo;
        }).collect(Collectors.toList());
        return collect;
    }

}
